#!/usr/bin/python
# -*- coding: utf-8 -*-

#Copyright (C) 1999-2003 Ben Gertzfield <che@debian.org>
#Copyright (C) 2005 Francois du Toit <che@debian.org>


import CDDB, DiscID, re, os, sys, avkutil, eyeD3, apev2tag
#from easygui import *


def disc_idmp3(cd):
    last = len(cd)

    track_frames = []
    checksum = 0
    cdtime = 0
    
    adjust = 0
#    f.getPlayTime()
#if eyeD3.isMp3File(f):
#     audioFile = eyeD3.Mp3AudioFile(f)
#     tag = audioFile.getTag()

    print
    for i in range(0, last):
#	mf = mad.MadFile(cd[i-1])    #madfile length calculation not that good
#	ms = mf.total_time()
	try:
	    audioFile = eyeD3.Mp3AudioFile(cd[i-1])
	except eyeD3.tag.TagException, value:
	    print avkutil.color(value,'lred')
	br = audioFile.getBitRate()
	pt = audioFile.getPlayTimeString()
	ms = audioFile.playTime * 1000
	ms = ms + adjust
	if i == 0:
	    ms = 2000
	cdtime = cdtime + ms
	(min, sec, frame) = (cdtime/60000,(cdtime%60000)/1000, (((cdtime%60000)%1000)*75)/1000 )
	print '%02d:%02d.%02d  vbr=%d br=%d %s %s' %(min,sec,frame,br[0],br[1],pt,cd[i-1])
	checksum = checksum + DiscID.cddb_sum(min*60 + sec)
	track_frames.append(min*60*75 + sec*75 + frame)

#    mf = mad.MadFile(cd[-1])  #madfile length calculation not that good
#    ms = mf.total_time()
    audioFile = eyeD3.Mp3AudioFile(cd[-1])
    ms = audioFile.playTime * 1000
    ms = ms + adjust
    cdtime = cdtime + ms
    (min, sec, frame) = (cdtime/60000,(cdtime%60000)/1000, (((cdtime%60000)%1000)*75)/1000 )
    track_frames.append(min*60*75 + sec*75 + frame)

    total_time = (track_frames[-1] / 75) - (track_frames[0] / 75)
	       
    discid = ((checksum % 0xff) << 24 | total_time << 8 | last)

    for i in range(0, last-1):
	secs = (track_frames[i+1] - track_frames[i])/75
	min = secs/60
	sec = secs%60
	print '%02d:%02d' %(min,sec)

    return [discid, last] + track_frames[:-1] + [ track_frames[-1] / 75 ]



###########################################################################



servers = []
#servers.append('http://127.0.0.1/cgi-bin/cddb.cgi')
servers.append('http://freedb.freedb.org/~cddb/cddb.cgi')
servers.append('http://us.freedb.org/~cddb/cddb.cgi')
#servers.append('http://cddb.com/~cddb/cddb.cgi')

discs = {}

fileExtList = ['.mp3','.MP3','.Mp3','.mP3']
files = [f for f in os.listdir(os.getcwd()) if os.path.isfile(f)]
files = [f for f in files if os.path.splitext(f)[1] in fileExtList]
files.sort()

#cdrom = open('/dev/cdroms/cdrom0')
#disc_id = DiscID.disc_id(cdrom)
#print disc_id

disc_id = disc_idmp3(files)
sys.stdout.write('cddb-tool template %X' %abs(disc_id[0]))
for i in range(1, len(disc_id)):
    sys.stdout.write(' %s' %disc_id[i])
print

if len(sys.argv) <= 1:
    for server in servers:
	try:
	    print 'trying server: %s' %server
	    print disc_id,server
	    (query_status, query_info) = CDDB.query(disc_id,server)
	    print query_status, query_info
	    if query_status == 200:
		print avkutil.color('200: Success','lgreen')
		break
	    elif query_status == 211:
		print avkutil.color('211: Multiple inexact matches were found','lgreen')
		break
	    elif query_status == 210:
		print avkutil.color('210: Multiple exact matches were found','lgreen')
		break
	    elif query_status == 202:
		print avkutil.color('202: No match found','lred')
	    elif query_status == 403:
		print avkutil.color('403: Error; database entry is corrupt','lred')
	    elif query_status == 409:
		print avkutil.color('409: Error; no handshake. (client-side error?)','lred')
	    else:
		print avkutil.color('Unknown Error','lred')
		
	except IOError, value:
	    print avkutil.color(value[1][1],'lred')


    if not query_info:
	print avkutil.color("Couldn't find a match on any server",'lred')
	sys.exit()
    nn = 1
    print query_info
    for y in query_info:
	print '%-10s %-10s %s' %(y['category'], y['disc_id'], y['title'])
	(read_status, read_info) = CDDB.read(y['category'], y['disc_id'], server)
	discs[ str(nn)+ '-' + str(read_info['revision']) +'-'+ str(y['disc_id']) ] = read_info
	nn += 1
	print
	print read_info
	print

#if query_status == 210: 
#    query_info = query_info[0]
elif len(sys.argv) > 1:
    cddbchecksum = sys.argv[1]
    category     = sys.argv[2]
    print '%-10s %-10s' %(category, cddbchecksum)
    (read_status, read_info) = CDDB.read(category, cddbchecksum, servers[0])
    discs[ str(read_info['revision']) +'-'+ str(cddbchecksum) ] = read_info
    
    print '%-10s %-10s' %(category, cddbchecksum)
    


	
#    keys = read_info.keys()
#    keys.sort()
#    for x in keys:
#	print '%-20s : %s' %(x, read_info[x])
#    print	

#discs = {}
#(read_status, read_info) = CDDB.read(query_info[0]['category'], query_info[0]['disc_id'],server)
#discs[read_info['revision']] = read_info


fieldNames = []
fieldValues = []
tags = {}
keys = discs.keys()
keys.sort()
print keys
#keys = keys[-1:]
nr = 1
for x in keys:
    titlep = re.compile(r'(.*)\s*/\s*(.*)')
    titlem = titlep.match(discs[x]['DTITLE'])
    if titlem:
        albumartist = titlem.group(1)
        albumtitle  = titlem.group(2)
    else:
        albumartist = ''
        albumtitle  = ''
    print
    print avkutil.color('NR:\t\t '+str(nr),'lred')
    print avkutil.color('Revision:\t '+str(discs[x]['revision']),'lblue')
    print avkutil.color('Submitted by:\t '+str(discs[x]['submitted_via']),'lblue')
    print avkutil.color('Artist:\t\t '+albumartist,'yellow')
    print avkutil.color('Title:\t\t '+albumtitle ,'yellow')
    print avkutil.color('DiscID:\t\t '+discs[x]['DISCID'],'yellow')
    print avkutil.color('Year:\t\t '+discs[x]['DYEAR'],'yellow')
    print avkutil.color('Genre:\t\t '+discs[x]['DGENRE'],'yellow')
    for i in range(0, disc_id[1]):
	if i%2:
	    sys.stdout.write(avkutil.color('%02d] %-40s' %(i+1, discs[x]['TTITLE' + `i`]),'white'))
	    print avkutil.color('\t%s' %(discs[x]['EXTT' + `i`]),'lgray')
	else:
	    sys.stdout.write(avkutil.color('%02d] %-40s' %(i+1, discs[x]['TTITLE' + `i`]),'lblue'))
	    print avkutil.color('\t%s' %(discs[x]['EXTT' + `i`]),'gray')
    print avkutil.color('Extra info:\t ','yellow') + avkutil.color(discs[x]['EXTD'],'lgray')
    print
    nr = nr + 1

try:
    whichdisc = int(raw_input(avkutil.color("\nWhich NR do you want? ",'yellow')))
except:
    whichdisc = 0
if whichdisc > len(keys) or whichdisc < 1:
    x = keys[-1]
else:
    x = keys[whichdisc - 1]


titlep = re.compile(r'(.*) / (.*)')
titlem = titlep.match(discs[x]['DTITLE'].decode('latin-1'))
albumartist = titlem.group(1)
albumtitle  = titlem.group(2)
fieldNames.append('Album Artist')
fieldValues.append(albumartist)
fieldNames.append('Album Title')
fieldValues.append(albumtitle)
fieldNames.append('CDDB ID')
fieldValues.append(discs[x]['DISCID'].decode('latin-1'))
fieldNames.append('Year')
fieldValues.append(discs[x]['DYEAR'].decode('latin-1'))
fieldNames.append('Genre')
fieldValues.append(discs[x]['DGENRE'].decode('latin-1'))
for i in range(0, disc_id[1]):
    fieldNames.append('Track %02d' %(i+1))
    fieldValues.append(discs[x]['TTITLE' + `i`].decode('latin-1'))
for i in range(0, disc_id[1]):
    fieldNames.append('EXT Track %02d' %(i+1))
    fieldValues.append(discs[x]['EXTT' + `i`].decode('latin-1'))

msg = "Correct CDDB information if you want "
title = "CDDB CD Information"
fieldValues = multenterbox(msg, title, fieldNames, fieldValues)

#print "Reply was:", fieldValues

extendedinfo = discs[x]['EXTD'].decode('latin-1').strip()

trk = 1
hasdiscid = 0
for x in files:
    tag = eyeD3.Tag()
    tag.link(x)
    tag.setVersion(eyeD3.ID3_V2_3)
    tag.setArtist(fieldValues[0].strip())
    tag.setAlbum(fieldValues[1].strip())
    # remove empty tags
#    for i in range(0, len(tag)):
#	if re.compile(r'^\s*$').search(tag[i]['text']):
#	    tag[i] = { 'frameid' : 'PRIV', 'text' : 'will be gone soon', 'description': 'del me' }


    tag.addUserTextFrame('DISCID',fieldValues[2])
 #   for frame in tag.frames:
#	if frame['frameid'] == 'TXXX' and tag[i]['description'] == 'DISCID':
#	    tag[i] = { 'frameid' : 'TXXX', 'text' : fieldValues[2], 'description': 'DISCID' }
#	    hasdiscid = 1
#    if hasdiscid != 1:
#	tag.append({ 'frameid' : 'TXXX', 'text' : fieldValues[2], 'description': 'DISCID' })
#    tag.setDate('')
#    tag.setDate(fieldValues[3].strip())
    tag.setDate(fieldValues[3].strip())
#    tag.setGenre(fieldValues[4].strip())
    tag.setGenre('')
    tag.setTrackNum((trk, disc_id[1]))
    if re.compile(r'.* / .*').search(fieldValues[4+trk]):
	tag.setArtist(re.compile(r'(.*) / (.*)').search(fieldValues[4+trk]).group(1).strip())
	tag.setTitle(re.compile(r'(.*) / (.*)').search(fieldValues[4+trk]).group(2).strip())
    else:
	tag.setTitle(fieldValues[4+trk].strip())

    tag.addComment(extendedinfo,'Extra Album info')
    tag.addComment(fieldValues[4 + trk + disc_id[1]].strip(),'Extra Track info')
    

 #   try:
 #       while 1:    tag.remove('PRIV')
#    except ValueError:
#	pass	
#    try:
#        while 1:    tag.remove('APIC')
#    except ValueError:
#	pass	
#    try:
#        while 1:    tag.remove('RVAD')
#    except ValueError:
#	pass	
#    try:
#        while 1:    tag.remove('GEOB')
#    except ValueError:
#	pass
#    try:
#        while 1:    tag.remove('WXXX')
#    except ValueError:
#	pass	
#    try:
#        while 1:    tag.remove('MCDI')
#    except ValueError:
#	pass	
#    try:
#        while 1:    tag.remove('UFID')
#    except ValueError:
#	pass	
	
    trk = trk + 1

#   get apetag
    apetag = {}
    try:
	apefile = open(x,'rb')
	apetag = apev2tag.apev2tag(apefile, action='getfields')
	apefile.close()
	
    except apev2tag.TagError, error:
	print error, error.getmoreinfo(), x
    except:
	apetag = {}


	
    for t in apetag:
	tag.addUserTextFrame(t, apetag[t])

#    hasapetag = 0
#    for t in apetag:
#	for i in range(0, len(tag)):
#	    if tag[i]['frameid'] == 'TXXX' and tag[i]['description'].lower() == t.lower():
#		if re.compile("replaygain", re.IGNORECASE).search(tag[i]['description']):
#		    tag[i] = { 'frameid' : 'TXXX', 'text' : apetag[t], 'description': t.lower() }
#		else:
#		    tag[i] = { 'frameid' : 'TXXX', 'text' : apetag[t], 'description': t }
#		hasapetag = 1
#	if hasapetag != 1:
#	    if re.compile("replaygain", re.IGNORECASE).search(t):
#		if not re.compile("mp3gain", re.IGNORECASE).search(t):
#		    tag.append({ 'frameid' : 'TXXX', 'text' : apetag[t], 'description': t.lower() })
#	    else:
#		if not re.compile("mp3gain", re.IGNORECASE).search(t):
#		    tag.append({ 'frameid' : 'TXXX', 'text' : apetag[t], 'description': t })
#	    hasapetag = 0

#   print tags	
    print
    print avkutil.color(x,'white')
    print tag.getVersionStr()
    for frame in tag.frames:
	if isinstance(frame, eyeD3.CommentFrame):
	    print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.comment)
	elif isinstance(frame, eyeD3.UserTextFrame):
	    print '%-40s [%s] - %s: %s' %(frame.getFrameDesc(), frame.header.id, frame.description, frame.text)
	elif isinstance(frame, eyeD3.TextFrame):
	    print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.text)
	elif isinstance(frame, eyeD3.UserURLFrame):
	    print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.url)
	elif isinstance(frame, eyeD3.ImageFrame):
	    frame.writeFile('',x + ' - ' + frame.getDefaultFileName())
	    tag.addImage(frame.pictureType,None,None)
	    print '%-40s [%s] - %s\timage removed (not permanent yet) and written to file' \
		%(frame.getFrameDesc(), frame.header.id, frame.getDefaultFileName())
	else:
	    print '%-40s [%s]' %(frame.getFrameDesc(), frame.header.id)

#	if frame['frameid'] == 'TXXX':
#	    print '%-7s - %s' %(tag[i]['description'], tag[i]['text'])
#	else:
#	    print tag[i]['frameid']
#	    try:
#		print '%-7s - %s' %(tag[i]['frameid'], tag[i]['text'])
#	    except:
#		print '%s caused an error' %tag[i]['frameid']
#		sys.exit()
	
#   print tag[0:]
    tags[x] = tag


#for x in files:
#    tagx = tags[x]
#    print avkutil.color(x,'white')
#    for frame in tagx.frames:
#	if isinstance(frame, eyeD3.CommentFrame):
#	    print '%-7s - %s' %(frame.header.id, frame.comment)
#	else:
#	    print '%-7s - %s' %(frame.header.id, frame.text)

confirm = raw_input(avkutil.color("\nDo you want to retag? ",'yellow'))
if confirm == 'y':
    for x in files:
	try:
	    apefile = open(x,'r+b')
            apev2tag.apev2tag(apefile, action='delete')
	    apefile.close()
	except apev2tag.TagError, error:
            print error, error.getmoreinfo(), x

	tagx = eyeD3.Tag()
	tagx.link(x)
	tagx = tags[x]
        enc = eyeD3.LATIN1_ENCODING
#        enc = eyeD3.UTF_8_ENCODING
#        enc = eyeD3.UTF_16BE_ENCODING
#        enc = eyeD3.UTF_16_ENCODING
	tagx.setTextEncoding(enc)
	tagx.setVersion(eyeD3.ID3_V2_3)
	
	print
	print avkutil.color(x,'white')
	print tagx.getVersionStr()
	
	for frame in tagx.frames:
	    if isinstance(frame, eyeD3.CommentFrame):
		print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.comment)
	    elif isinstance(frame, eyeD3.UserTextFrame):
		print '%-40s [%s] - %s: %s' %(frame.getFrameDesc(), frame.header.id, frame.description, frame.text)
	    elif isinstance(frame, eyeD3.TextFrame):
		print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.text)
	    elif isinstance(frame, eyeD3.UserURLFrame):
		print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.url)
	    elif isinstance(frame, eyeD3.ImageFrame):
		print '%-40s [%s] - %s' %(frame.getFrameDesc(), frame.header.id, frame.getDefaultFileName())
	    else:
		print '%-40s [%s]' %(frame.getFrameDesc(), frame.header.id)

#	tagx.remove()
	tagx.update(eyeD3.ID3_V2_3)
	if tagx.getGenre() not in eyeD3.genres:
	    tagx.setGenre('Negerpunk')
	tagx.update(eyeD3.ID3_V1_1)
	
else:
    print 'Did nothing'
	    

